package com.hiutil.cbo;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

public class MethodsFactory {
	/**
	 * 根据数据类型取得函数对象
	 * @param methodName
	 * @param type
	 * @return
	 */
	public static Method getMethod(String methodName, Class<?> type) {
		if (null == type || null == methodName) {
			return null;
		}
		if (!classMethodLibrary.containsKey(type)) {
			loadMethods(type);
		}
		if (!classMethodLibrary.containsKey(type)) {
			return null;
		}
		Map<String, Method> map = classMethodLibrary.get(type);
		if (null == map) {
			return null;
		}

		String methodKey = methodName.toLowerCase();
		if (!map.containsKey(methodKey)) {
			return null;
		}

		return map.get(methodKey);
	}

	/**
	 * 取得对象的属性值
	 * @param t 对象
	 * @param field 属性(不含get,set)
	 * @param classZ 类型
	 * @return 转换为字符串后的值
	 */
	public static <T> String getPropertyValue(T t, String field, Class<T> classZ) {
		if (null == field || null == t || null == classZ) {
			return null;
		}
		String methodName = "get" + field;
		methodName = methodName.toLowerCase();
		Method method = getMethod(methodName, classZ);
		if (null == method) {
			return null;
		}

		if (method.getParameterCount() > 0) {
			return null;
		}

		Class<?> retType = method.getReturnType();
		if (void.class == retType) {
			return null;
		}

		try {
			Object obj = method.invoke(t);
			return HiTypeHelper.objectToString(obj, retType);
		} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
			e.printStackTrace();
			return null;
		}
	}

	private static void loadMethods(Class<?> type) {
		if (null == type) {
			return;
		}

		if (classMethodLibrary.containsKey(type)) {
			return;
		}

    	Method[] methods = type.getMethods();
    	Map<String, Method> map = new HashMap<String, Method>();
    	for (int i = 0; i < methods.length; i++) {
    		Method method = methods[i];
    		if (null == method) {
    			continue;
    		}
    		String name = method.getName();
    		if (null == name || name.trim().equals("")) {
    			continue;
    		}

    		name = name.toLowerCase();
    		if (map.containsKey(name)) {
    			continue;
    		}
    		map.put(name, method);
    	}

    	classMethodLibrary.put(type, map);
	}

	private static Map<Class<?>, Map<String, Method>> classMethodLibrary = new HashMap<Class<?>, Map<String, Method>>();
}
